import { BaseService } from './base.service'
import { User } from '@/types/sheet'
import { ServiceRegistry } from './base.service'
import bcrypt from 'bcryptjs'
import jwt from 'jsonwebtoken'

export interface CreateUserData {
  name: string
  email: string
  password: string
  avatar?: string
}

export interface UpdateUserData {
  name?: string
  email?: string
  avatar?: string
}

export interface LoginCredentials {
  email: string
  password: string
}

export interface AuthResult {
  user: User
  token: string
}

export class UserService extends BaseService {
  constructor() {
    super()
    ServiceRegistry.getInstance().register('user', this)
  }

  // 创建用户
  async createUser(data: CreateUserData): Promise<User> {
    return await this.executeWithResilience(async () => {
      // 检查邮箱是否已存在
      const existingUser = await this.prisma.user.findUnique({
        where: { email: data.email }
      })

      if (existingUser) {
        throw new Error('Email already exists')
      }

      // 加密密码
      const hashedPassword = await bcrypt.hash(data.password, 12)

      const user = await this.prisma.user.create({
        data: {
          name: data.name,
          email: data.email,
          password: hashedPassword,
          avatar: data.avatar
        }
      })
      
      // 转换类型以匹配 User
      return {
        ...user,
        avatar: user.avatar ?? undefined
      } as User
    })
  }

  // 根据ID获取用户
  async getUserById(id: string): Promise<User | null> {
    return await this.executeWithResilience(async () => {
      const user = await this.prisma.user.findUnique({
        where: { id }
      })
      
      if (!user) return null
      
      // 转换类型以匹配 User
      return {
        ...user,
        avatar: user.avatar ?? undefined
      } as User
    })
  }

  // 根据邮箱获取用户
  async getUserByEmail(email: string): Promise<User | null> {
    return await this.executeWithResilience(async () => {
      const user = await this.prisma.user.findUnique({
        where: { email }
      })
      
      if (!user) return null
      
      // 转换类型以匹配 User
      return {
        ...user,
        avatar: user.avatar ?? undefined
      } as User
    })
  }

  // 更新用户信息
  async updateUser(id: string, data: UpdateUserData): Promise<User> {
    return await this.executeWithResilience(async () => {
      const user = await this.prisma.user.update({
        where: { id },
        data: {
          ...data,
          updatedAt: new Date()
        }
      })
      
      // 转换类型以匹配 User
      return {
        ...user,
        avatar: user.avatar ?? undefined
      } as User
    })
  }

  // 删除用户
  async deleteUser(id: string): Promise<void> {
    await this.executeWithResilience(async () => {
      await this.prisma.user.delete({
        where: { id }
      })
    })
  }

  // 验证密码
  async validatePassword(userId: string, password: string): Promise<boolean> {
    const user = await this.prisma.user.findUnique({
      where: { id: userId },
      select: { password: true }
    })
    
    if (!user) return false
    
    return await bcrypt.compare(password, user.password)
  }

  // 用户登录
  async login(credentials: LoginCredentials): Promise<AuthResult> {
    const user = await this.getUserByEmail(credentials.email)
    
    if (!user) {
      throw new Error('Invalid credentials')
    }

    const isValidPassword = await this.validatePassword(user.id, credentials.password)
    
    if (!isValidPassword) {
      throw new Error('Invalid credentials')
    }

    // 生成JWT token
    const token = jwt.sign(
      { 
        userId: user.id,
        email: user.email 
      },
      process.env.JWT_SECRET || 'sheet_secret',
      { expiresIn: '7d' }
    )

    return {
      user: {
        id: user.id,
        name: user.name,
        email: user.email,
        avatar: user.avatar,
        createdAt: user.createdAt,
        updatedAt: user.updatedAt
      },
      token
    }
  }

  // 验证JWT token
  async verifyToken(token: string): Promise<User | null> {
    try {
      console.log('=== verifyToken Debug ===')
      console.log('Token to verify:', token ? `${token.substring(0, 20)}...` : 'null')
      console.log('JWT_SECRET:', process.env.JWT_SECRET ? 'Set' : 'Not set')
      
      const decoded = jwt.verify(token, process.env.JWT_SECRET || 'sheet_secret') as any
      console.log('Token decoded successfully:', decoded)
      
      const user = await this.getUserById(decoded.userId)
      console.log('User found by ID:', user ? `ID: ${user.id}, Email: ${user.email}` : 'Not found')
      
      return user
    } catch (error) {
      console.log('Token verification failed:', error instanceof Error ? error.message : 'Unknown error')
      return null
    }
  }

  // 更改密码
  async changePassword(userId: string, oldPassword: string, newPassword: string): Promise<void> {
    const user = await this.getUserById(userId)
    
    if (!user) {
      throw new Error('User not found')
    }

    const isValidPassword = await this.validatePassword(user.id, oldPassword)
    
    if (!isValidPassword) {
      throw new Error('Invalid old password')
    }

    const hashedNewPassword = await bcrypt.hash(newPassword, 12)

    await this.executeWithResilience(async () => {
      await this.prisma.user.update({
        where: { id: userId },
        data: { password: hashedNewPassword }
      })
    })
  }

  // 重置密码
  async resetPassword(email: string, newPassword: string): Promise<void> {
    const user = await this.getUserByEmail(email)
    
    if (!user) {
      throw new Error('User not found')
    }

    const hashedPassword = await bcrypt.hash(newPassword, 12)

    await this.executeWithResilience(async () => {
      await this.prisma.user.update({
        where: { id: user.id },
        data: { password: hashedPassword }
      })
    })
  }

  // 获取用户统计信息
  async getUserStats(userId: string): Promise<{
    totalSheets: number
    ownedSheets: number
    sharedSheets: number
    totalCells: number
  }> {
    return await this.executeWithResilience(async () => {
      const [totalSheets, ownedSheets, sharedSheets, totalCells] = await Promise.all([
        this.prisma.sheet.count({
          where: {
            OR: [
              { ownerId: userId },
              {
                members: {
                  some: { userId }
                }
              }
            ]
          }
        }),
        this.prisma.sheet.count({
          where: { ownerId: userId }
        }),
        this.prisma.sheet.count({
          where: {
            members: {
              some: { userId }
            }
          }
        }),
        this.prisma.cell.count({
          where: {
            sheet: {
              OR: [
                { ownerId: userId },
                {
                  members: {
                    some: { userId }
                  }
                }
              ]
            }
          }
        })
      ])

      return {
        totalSheets,
        ownedSheets,
        sharedSheets,
        totalCells
      }
    })
  }
}
